
<!doctype html>
<html lang="en" class="no-js">
  <head>
    
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1">
      
        <meta name="description" content="Starry设计文档">
      
      
      
      
        <link rel="prev" href="../%E4%BF%A1%E5%8F%B7%E6%A8%A1%E5%9D%97-axsignal/">
      
      
        <link rel="next" href="../%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%A8%A1%E5%9D%97-axfs/">
      
      <link rel="icon" href="../../assets/images/favicon.png">
      <meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.1.21">
    
    
      
        <title>任务调度模块-axtask - Starry</title>
      
    
    
      <link rel="stylesheet" href="../../assets/stylesheets/main.eebd395e.min.css">
      
        
        <link rel="stylesheet" href="../../assets/stylesheets/palette.ecc896b0.min.css">
      
      

    
    
    
      
        
        
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
      
    
    
      <link rel="stylesheet" href="../../resources/css/extra.css">
    
    <script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
    
      

    
    
    
  </head>
  
  
    
    
      
    
    
    
    
    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="blue" data-md-color-accent="cyan">
  
    
    
      <script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
    
    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
    <label class="md-overlay" for="__drawer"></label>
    <div data-md-component="skip">
      
        
        <a href="#task" class="md-skip">
          Skip to content
        </a>
      
    </div>
    <div data-md-component="announce">
      
    </div>
    
    
      

  

<header class="md-header md-header--shadow" data-md-component="header">
  <nav class="md-header__inner md-grid" aria-label="Header">
    <a href="../.." title="Starry" class="md-header__button md-logo" aria-label="Starry" data-md-component="logo">
      
  
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>

    </a>
    <label class="md-header__button md-icon" for="__drawer">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
    </label>
    <div class="md-header__title" data-md-component="header-title">
      <div class="md-header__ellipsis">
        <div class="md-header__topic">
          <span class="md-ellipsis">
            Starry
          </span>
        </div>
        <div class="md-header__topic" data-md-component="header-topic">
          <span class="md-ellipsis">
            
              任务调度模块-axtask
            
          </span>
        </div>
      </div>
    </div>
    
      
        <form class="md-header__option" data-md-component="palette">
          
            
            
            
            <input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="blue" data-md-color-accent="cyan"  aria-label="切换至夜间模式"  type="radio" name="__palette" id="__palette_1">
            
              <label class="md-header__button md-icon" title="切换至夜间模式" for="__palette_2" hidden>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3 3.19.09m3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95 2.06.05m-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31Z"/></svg>
              </label>
            
          
            
            
            
            <input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="cyan"  aria-label="切换至日间模式"  type="radio" name="__palette" id="__palette_2">
            
              <label class="md-header__button md-icon" title="切换至日间模式" for="__palette_1" hidden>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5c-.84 0-1.65.15-2.39.42L12 2M3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29L3.34 7m.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14L3.36 17M20.65 7l-1.77 3.79a7.023 7.023 0 0 0-2.38-4.15l4.15.36m-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29L20.64 17M12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44L12 22Z"/></svg>
              </label>
            
          
        </form>
      
    
    
    
      <label class="md-header__button md-icon" for="__search">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
      </label>
      <div class="md-search" data-md-component="search" role="dialog">
  <label class="md-search__overlay" for="__search"></label>
  <div class="md-search__inner" role="search">
    <form class="md-search__form" name="search">
      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
      <label class="md-search__icon md-icon" for="__search">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
      </label>
      <nav class="md-search__options" aria-label="Search">
        
        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
        </button>
      </nav>
      
    </form>
    <div class="md-search__output">
      <div class="md-search__scrollwrap" data-md-scrollfix>
        <div class="md-search-result" data-md-component="search-result">
          <div class="md-search-result__meta">
            Initializing search
          </div>
          <ol class="md-search-result__list" role="presentation"></ol>
        </div>
      </div>
    </div>
  </div>
</div>
    
    
  </nav>
  
</header>
    
    <div class="md-container" data-md-component="container">
      
      
        
          
        
      
      <main class="md-main" data-md-component="main">
        <div class="md-main__inner md-grid">
          
            
              
              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
                <div class="md-sidebar__scrollwrap">
                  <div class="md-sidebar__inner">
                    


<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
  <label class="md-nav__title" for="__drawer">
    <a href="../.." title="Starry" class="md-nav__button md-logo" aria-label="Starry" data-md-component="logo">
      
  
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>

    </a>
    Starry
  </label>
  
  <ul class="md-nav__list" data-md-scrollfix>
    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="../.." class="md-nav__link">
        Starry
      </a>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="../../%E6%A6%82%E8%BF%B0/" class="md-nav__link">
        概述
      </a>
    </li>
  

    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
      
      
      
        <label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
          架构设计
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
        <label class="md-nav__title" for="__nav_3">
          <span class="md-nav__icon md-icon"></span>
          架构设计
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../../%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/ArceOS%E4%BB%8B%E7%BB%8D/" class="md-nav__link">
        ArceOS介绍
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../../%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/Starry%E7%BB%93%E6%9E%84%E8%AF%B4%E6%98%8E/" class="md-nav__link">
        Starry结构说明
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="../../%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF/" class="md-nav__link">
        设计思路
      </a>
    </li>
  

    
      
      
      

  
  
    
  
  
    
    <li class="md-nav__item md-nav__item--active md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
      
      
      
        <label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
          模块介绍
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
        <label class="md-nav__title" for="__nav_5">
          <span class="md-nav__icon md-icon"></span>
          模块介绍
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E5%86%85%E6%A0%B8%E5%BA%95%E5%B1%82%E6%A8%A1%E5%9D%97-axhal/" class="md-nav__link">
        内核底层模块-axhal
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97-axmem/" class="md-nav__link">
        内存管理模块-axmem
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E7%BD%91%E7%BB%9C%E6%A8%A1%E5%9D%97-axnet/" class="md-nav__link">
        网络模块-axnet
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E4%BF%A1%E5%8F%B7%E6%A8%A1%E5%9D%97-axsignal/" class="md-nav__link">
        信号模块-axsignal
      </a>
    </li>
  

            
          
            
              
  
  
    
  
  
    <li class="md-nav__item md-nav__item--active">
      
      <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
      
      
      
        <label class="md-nav__link md-nav__link--active" for="__toc">
          任务调度模块-axtask
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <a href="./" class="md-nav__link md-nav__link--active">
        任务调度模块-axtask
      </a>
      
        

<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
  
  
  
  
    <label class="md-nav__title" for="__toc">
      <span class="md-nav__icon md-icon"></span>
      Table of contents
    </label>
    <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
      
        <li class="md-nav__item">
  <a href="#task" class="md-nav__link">
    task
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#run_queue" class="md-nav__link">
    run_queue
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#stat" class="md-nav__link">
    stat
  </a>
  
</li>
      
    </ul>
  
</nav>
      
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%A8%A1%E5%9D%97-axfs/" class="md-nav__link">
        文件系统模块-axfs
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E8%BF%9B%E7%A8%8B%E6%8E%A7%E5%88%B6%E6%A8%A1%E5%9D%97-axprocess/" class="md-nav__link">
        进程控制模块-axprocess
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E5%86%85%E6%A0%B8%E8%BF%90%E8%A1%8C%E6%97%B6%E6%A8%A1%E5%9D%97-axruntime/" class="md-nav__link">
        内核运行时模块-axruntime
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../%E5%AE%8F%E5%86%85%E6%A0%B8%E7%94%A8%E6%88%B7%E5%BA%93-starry/" class="md-nav__link">
        宏内核用户库-starry
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
      
      
      
        <label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
          实现重点
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
        <label class="md-nav__title" for="__nav_6">
          <span class="md-nav__icon md-icon"></span>
          实现重点
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../../%E5%AE%9E%E7%8E%B0%E9%87%8D%E7%82%B9/%E4%BE%9D%E8%B5%96%E9%97%AE%E9%A2%98/" class="md-nav__link">
        依赖问题
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../../%E5%AE%9E%E7%8E%B0%E9%87%8D%E7%82%B9/%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98/" class="md-nav__link">
        兼容问题
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../../%E5%AE%9E%E7%8E%B0%E9%87%8D%E7%82%B9/%E5%AE%8F%E5%86%85%E6%A0%B8%E5%8C%96%E6%8E%A2%E8%AE%A8/" class="md-nav__link">
        宏内核化探讨
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="../../%E9%97%AE%E9%A2%98%E4%B8%8E%E8%A7%A3%E5%86%B3/" class="md-nav__link">
        问题与解决
      </a>
    </li>
  

    
  </ul>
</nav>
                  </div>
                </div>
              </div>
            
            
              
              <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
                <div class="md-sidebar__scrollwrap">
                  <div class="md-sidebar__inner">
                    

<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
  
  
  
  
    <label class="md-nav__title" for="__toc">
      <span class="md-nav__icon md-icon"></span>
      Table of contents
    </label>
    <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
      
        <li class="md-nav__item">
  <a href="#task" class="md-nav__link">
    task
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#run_queue" class="md-nav__link">
    run_queue
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#stat" class="md-nav__link">
    stat
  </a>
  
</li>
      
    </ul>
  
</nav>
                  </div>
                </div>
              </div>
            
          
          
            <div class="md-content" data-md-component="content">
              <article class="md-content__inner md-typeset">
                
                  


  <h1>任务调度模块-axtask</h1>

<p>任务调度是内核实现过程中非常重要的环节。为了保证和上游arceos仓库较好的进行匹配，因此starry的任务调度机制基本参照了arceos的调度机制，并在此基础上进行了适配宏内核的调整。</p>
<p>为了实现宏内核架构体系，需要对原有Arceos的部分核心模块（如axtask）进行修改。为了防止合并时冲突过多，因此在对应模块下建立<code>monolithic_task</code>文件夹，存放为宏内核架构实现的内容。同时使用条件编译来选择是宏内核架构还是unikernel架构。</p>
<p>以下为Starry实现的任务调度模块的相关功能划分：</p>
<p><img alt="avatar" src="../../figures/axtask.png" /></p>
<p>对功能的额外补充说明如下：</p>
<h4 id="task">task<a class="headerlink" href="#task" title="Permanent link">&para;</a></h4>
<p>任务单元是内核运行过程中非常重要的组成部分，任务调度模块的组成如下：</p>
<div class="highlight"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">TaskInner</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">id</span>: <span class="nc">TaskId</span><span class="p">,</span>
<span class="w">    </span><span class="n">name</span>: <span class="nb">String</span><span class="p">,</span>
<span class="w">    </span><span class="n">is_idle</span>: <span class="kt">bool</span><span class="p">,</span>
<span class="w">    </span><span class="n">is_init</span>: <span class="kt">bool</span><span class="p">,</span>

<span class="w">    </span><span class="n">entry</span>: <span class="nb">Option</span><span class="o">&lt;*</span><span class="k">mut</span><span class="w"> </span><span class="k">dyn</span><span class="w"> </span><span class="nb">FnOnce</span><span class="p">()</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="n">state</span>: <span class="nc">AtomicU8</span><span class="p">,</span>

<span class="w">    </span><span class="n">in_wait_queue</span>: <span class="nc">AtomicBool</span><span class="p">,</span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;irq&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="n">in_timer_list</span>: <span class="nc">AtomicBool</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;preempt&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="n">need_resched</span>: <span class="nc">AtomicBool</span><span class="p">,</span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;preempt&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="n">preempt_disable_count</span>: <span class="nc">AtomicUsize</span><span class="p">,</span>

<span class="w">    </span><span class="n">exit_code</span>: <span class="nc">AtomicI32</span><span class="p">,</span>
<span class="w">    </span><span class="n">wait_for_exit</span>: <span class="nc">WaitQueue</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="n">kstack</span>: <span class="nb">Option</span><span class="o">&lt;</span><span class="n">TaskStack</span><span class="o">&gt;</span><span class="p">,</span>

<span class="w">    </span><span class="n">ctx</span>: <span class="nc">UnsafeCell</span><span class="o">&lt;</span><span class="n">TaskContext</span><span class="o">&gt;</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="c1">// 对应进程ID</span>
<span class="w">    </span><span class="n">process_id</span>: <span class="nc">AtomicU64</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="sd">/// 是否是所属进程下的主线程</span>
<span class="w">    </span><span class="n">is_leader</span>: <span class="nc">AtomicBool</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="c1">// 所属页表ID，在宏内核下默认会开启分页，是只读的所以不用原子量</span>
<span class="w">    </span><span class="n">page_table_token</span>: <span class="kt">usize</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="sd">/// 初始化的trap上下文</span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="n">trap_frame</span>: <span class="nc">UnsafeCell</span><span class="o">&lt;</span><span class="n">TrapFrame</span><span class="o">&gt;</span><span class="p">,</span>

<span class="w">    </span><span class="c1">// 时间统计</span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="n">time</span>: <span class="nc">UnsafeCell</span><span class="o">&lt;</span><span class="n">TimeStat</span><span class="o">&gt;</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[allow(unused)]</span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="sd">/// 子线程初始化的时候，存放tid的地址</span>
<span class="w">    </span><span class="n">set_child_tid</span>: <span class="nc">AtomicU64</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="sd">/// 子线程初始化时，将这个地址清空；子线程退出时，触发这里的 futex。</span>
<span class="w">    </span><span class="sd">/// 在创建时包含 CLONE_CHILD_SETTID 时才非0，但可以被 sys_set_tid_address 修改</span>
<span class="w">    </span><span class="n">clear_child_tid</span>: <span class="nc">AtomicU64</span><span class="p">,</span>

<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;monolithic&quot;</span><span class="cp">)]</span>
<span class="w">    </span><span class="sd">/// 退出时是否向父进程发送SIG_CHILD</span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="n">send_sigchld_when_exit</span>: <span class="nc">Bool</span><span class="p">,</span>
<span class="p">}</span>
</code></pre></div>
<p>可以看出，任务结构体中的某些字段包含着多核安全性，因为虽然一个任务仅会在一个CPU核上运行，但是不同CPU可能会同时访问同一个任务的某一个字段，导致出现多核冲突，因此需要为对应字段加上原子性。</p>
<p>另外，task字段也提供了某一个任务第一次执行的实现。它需要根据是否为宏内核架构分别进行实现。</p>
<ul>
<li>Arceos实现：在Arceos下，代码始终在内核态下运行，所以可以直接跳转到任务入口函数执行。因此会把入口函数的地址直接记录在task的entry字段上，并且在第一次执行任务时直接跳转到entry字段的地址即可。</li>
<li>Starry实现：在Starry下，任务会进入到用户态运行，此时需要把任务初始化的trap上下文放置到内核栈上，并且进行sret跳转。</li>
</ul>
<h3 id="run_queue">run_queue<a class="headerlink" href="#run_queue" title="Permanent link">&para;</a></h3>
<p>任务调度是任务模块实现的重点。接下来简要介绍以下starry的任务启动和调度流程。</p>
<p>当前任务调度机制是fifo队列法，启动和调度方式如下：</p>
<ul>
<li>单核情况</li>
</ul>
<p>对应代码在<code>modules/axtask/src/monolithic_task/run_queue.rs/init</code>函数中：</p>
<div class="highlight"><pre><span></span><code><span class="k">pub</span><span class="p">(</span><span class="k">crate</span><span class="p">)</span><span class="w"> </span><span class="k">fn</span> <span class="nf">init</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">IDLE_TASK_STACK_SIZE</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mh">0x20000</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">idle_task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">TaskInner</span>::<span class="n">new</span><span class="p">(</span>
<span class="w">        </span><span class="o">||</span><span class="w"> </span><span class="k">crate</span>::<span class="n">run_idle</span><span class="p">(),</span>
<span class="w">        </span><span class="s">&quot;idle&quot;</span><span class="p">.</span><span class="n">into</span><span class="p">(),</span>
<span class="w">        </span><span class="n">IDLE_TASK_STACK_SIZE</span><span class="p">,</span>
<span class="w">        </span><span class="n">KERNEL_PROCESS_ID</span><span class="p">,</span>
<span class="w">        </span><span class="mi">0</span><span class="p">,</span>
<span class="w">        </span><span class="kc">false</span><span class="p">,</span>
<span class="w">    </span><span class="p">);</span>
<span class="w">    </span><span class="n">IDLE_TASK</span><span class="p">.</span><span class="n">with_current</span><span class="p">(</span><span class="o">|</span><span class="n">i</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">LazyInit</span><span class="o">&lt;</span><span class="n">Arc</span><span class="o">&lt;</span><span class="n">scheduler</span>::<span class="n">FifoTask</span><span class="o">&lt;</span><span class="n">TaskInner</span><span class="o">&gt;&gt;&gt;|</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">i</span><span class="p">.</span><span class="n">init_by</span><span class="p">(</span><span class="n">idle_task</span><span class="p">.</span><span class="n">clone</span><span class="p">())</span>
<span class="w">    </span><span class="p">});</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">main_task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">TaskInner</span>::<span class="n">new_init</span><span class="p">(</span><span class="s">&quot;main&quot;</span><span class="p">.</span><span class="n">into</span><span class="p">());</span>
<span class="w">    </span><span class="n">main_task</span><span class="p">.</span><span class="n">set_state</span><span class="p">(</span><span class="n">TaskState</span>::<span class="n">Running</span><span class="p">);</span>

<span class="w">    </span><span class="n">RUN_QUEUE</span><span class="p">.</span><span class="n">init_by</span><span class="p">(</span><span class="n">AxRunQueue</span>::<span class="n">new</span><span class="p">());</span>
<span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">CurrentTask</span>::<span class="n">init_current</span><span class="p">(</span><span class="n">main_task</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>共包含三个任务：</p>
<ul>
<li>
<p>idle_task：拥有独立的trap上下文和任务上下文，任务上下文指向的入口是<code>run_idle</code>函数。</p>
</li>
<li>
<p>gc_task：在执行<code>AxRunQueue::new()</code>函数时生成，负责回收已经退出的任务。</p>
</li>
<li>
<p>main_task：内核运行时执行的任务，它的任务上下文为空，在被切换时会把当前的ra等信息写入任务上下文，从而可以在恢复时继续执行内核相关代码。</p>
</li>
</ul>
<p>当执行完init函数之后，CPU指向main_task，pc不变，继续执行当前代码，直到来到<code>modules/axruntime/src/lib.rs/rust_main</code>函数的<code>unsafe{main();}</code>入口，从而跳转到Arceos指定的用户程序（<strong>注意：虽然是用户程序，但是运行在arceos框架下，还处于内核态</strong>），开始加载测例。默认<code>make run</code>会运行<code>apps/syscall/busybox</code>程序。若测例程序会通过<code>clone</code>等方式生成新的任务，那么新任务会被加入到任务调度队列等待被调度。</p>
<ul>
<li>
<p>若调度队列中还有任务等待被调度，那么就会切换到对应任务。此时若调度的任务是gc，则gc会检测是否还有任务退出。若有任务已经退出等待回收，则gc会回收这些任务。若没有则阻塞gc本身，切换到其他任务。</p>
<p>gc的实现方式如下：</p>
<div class="highlight"><pre><span></span><code><span class="k">fn</span> <span class="nf">gc_entry</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">loop</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Drop all exited tasks and recycle resources.</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="o">!</span><span class="n">EXITED_TASKS</span><span class="p">.</span><span class="n">lock</span><span class="p">().</span><span class="n">is_empty</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="c1">// Do not do the slow drops in the critical section.</span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">EXITED_TASKS</span><span class="p">.</span><span class="n">lock</span><span class="p">().</span><span class="n">pop_front</span><span class="p">();</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">task</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="c1">// If the task reference is not taken after `spawn()`, it will be</span>
<span class="w">                </span><span class="c1">// dropped here. Otherwise, it will be dropped after the reference</span>
<span class="w">                </span><span class="c1">// is dropped (usually by `join()`).</span>
<span class="w">                </span><span class="c1">// info!(&quot;drop task: {}&quot;, task.id().as_u64());</span>
<span class="w">                </span><span class="nb">drop</span><span class="p">(</span><span class="n">task</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">        </span><span class="n">WAIT_FOR_EXIT</span><span class="p">.</span><span class="n">wait</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</li>
<li>
<p>若调度队列中没有下一个任务时，就会切换到idle_task，此时会执行<code>run_idle</code>函数，即不断执行<code>yield_task</code>函数，直到有新的任务加入调度队列，则切换到对应任务。</p>
<p>run_idle函数实现方式如下：</p>
<div class="highlight"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">run_idle</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="o">!</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">loop</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">yield_now</span><span class="p">();</span>
<span class="w">        </span><span class="n">debug</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;idle task: waiting for IRQs...&quot;</span><span class="p">);</span>
<span class="w">        </span><span class="cp">#[cfg(feature = </span><span class="s">&quot;irq&quot;</span><span class="cp">)]</span>
<span class="w">        </span><span class="n">axhal</span>::<span class="n">arch</span>::<span class="n">wait_for_irqs</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</li>
<li>
<p>多核启动</p>
</li>
</ul>
<p>我们只考虑任务调度相关，则多核情况下，其他核初始化的函数在<code>modules/axtask/src/monolithic_task/run_queue.rs/init_secondary</code>中，会新建一个<code>idle_task</code>，但是它的功能类似于单核启动下的<code>main_task</code>，即初始化时没有任务上下文，但是可以在被切换之后保留内核的任务执行流。</p>
<p>初始化完毕之后，每一个非主核指向一个<code>idle_task</code>，此时他们会继续执行内核中的初始化代码，最后在<code>modules/axruntime/src/mp.rs</code>的<code>rust_main_secondary</code>函数中执行<code>run_idle</code>函数，即不断地<code>yield</code>自己，直到有新的任务加入调度队列。</p>
<p>当测例对应的用户态任务执行<code>clone</code>系统调用，生成新的任务加入到调度队列时，此时就会随机分配一个CPU核获得该任务并且进行执行。这就是多核启动的原理。</p>
<h3 id="stat">stat<a class="headerlink" href="#stat" title="Permanent link">&para;</a></h3>
<p>stat实现了任务的时间记录功能和计时器功能。</p>
<p>记录任务运行时间是通过计算和更新时间戳进行的，每一个stat结构体都拥有如下结构：</p>
<div class="highlight"><pre><span></span><code><span class="sd">/// 用户态经过的时间，单位为纳秒</span>
<span class="n">utime_ns</span>: <span class="kt">usize</span><span class="p">,</span>
<span class="sd">/// 内核态经过的时间，单位为纳秒</span>
<span class="n">stime_ns</span>: <span class="kt">usize</span><span class="p">,</span>
<span class="sd">/// 进入用户态时标记当前时间戳，用于统计用户态时间</span>
<span class="n">user_tick</span>: <span class="kt">usize</span><span class="p">,</span>
<span class="sd">/// 进入内核态时标记当前时间戳，用于统计内核态时间</span>
<span class="n">kernel_tick</span>: <span class="kt">usize</span><span class="p">,</span>
</code></pre></div>
<p>更新时间戳的时间点共有四个：</p>
<ul>
<li>从用户态进入内核态</li>
<li>从内核态进入用户态</li>
<li>切换到本任务</li>
<li>本任务被切换走</li>
</ul>
<p>相关更新运行时间的代码如下：</p>
<div class="highlight"><pre><span></span><code><span class="sd">/// 从用户态进入内核态，记录当前时间戳，统计用户态时间</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">into_kernel_mode</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">tid</span>: <span class="kt">isize</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">current_time_nanos</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">delta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">user_tick</span><span class="p">;</span>
<span class="w">    </span><span class="bp">self</span><span class="p">.</span><span class="n">utime_ns</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">delta</span><span class="p">;</span>
<span class="w">    </span><span class="bp">self</span><span class="p">.</span><span class="n">kernel_tick</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">now_time_ns</span><span class="p">;</span>
<span class="p">}</span>
<span class="sd">/// 从内核态进入用户态，记录当前时间戳，统计内核态时间</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">into_user_mode</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">tid</span>: <span class="kt">isize</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="c1">// 获取当前时间，单位为纳秒</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">current_time_nanos</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">delta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">kernel_tick</span><span class="p">;</span>
<span class="w">    </span><span class="bp">self</span><span class="p">.</span><span class="n">stime_ns</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">delta</span><span class="p">;</span>
<span class="w">    </span><span class="bp">self</span><span class="p">.</span><span class="n">user_tick</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">now_time_ns</span><span class="p">;</span>
<span class="p">}</span>
<span class="sd">/// 内核态下，当前任务被切换掉，统计内核态时间</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">swtich_from</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">tid</span>: <span class="kt">isize</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="c1">// 获取当前时间，单位为纳秒</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">current_time_nanos</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">delta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">kernel_tick</span><span class="p">;</span>
<span class="w">    </span><span class="bp">self</span><span class="p">.</span><span class="n">stime_ns</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">delta</span><span class="p">;</span>
<span class="p">}</span>
<span class="sd">/// 内核态下，切换到当前任务，更新内核态时间戳</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">switch_to</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">tid</span>: <span class="kt">isize</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="c1">// 获取当前时间，单位为纳秒</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">current_time_nanos</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">delta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">now_time_ns</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">kernel_tick</span><span class="p">;</span>
<span class="w">    </span><span class="c1">// 更新时间戳，方便当该任务被切换时统计内核经过的时间</span>
<span class="w">    </span><span class="bp">self</span><span class="p">.</span><span class="n">kernel_tick</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">now_time_ns</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>





                
              </article>
            </div>
          
          
        </div>
        
      </main>
      
        <footer class="md-footer">
  
  <div class="md-footer-meta md-typeset">
    <div class="md-footer-meta__inner md-grid">
      <div class="md-copyright">
  
  
    Made with
    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
      Material for MkDocs
    </a>
  
</div>
      
    </div>
  </div>
</footer>
      
    </div>
    <div class="md-dialog" data-md-component="dialog">
      <div class="md-dialog__inner md-typeset"></div>
    </div>
    
    <script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.74e28a9f.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
    
    
      <script src="../../assets/javascripts/bundle.220ee61c.min.js"></script>
      
    
  </body>
</html>